package net.area80.components
{
	import flash.display.DisplayObject;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	
	import gs.TweenLite;
	import gs.easing.Strong;
	
	import net.area80.components.skin.ABScrollbarSkin;
	
	public class VScrollbar extends Sprite
	{
		private var scrollObject:DisplayObject;
		private var snapHeight:Number;
		private var cSnap:uint = 0;
		private var initPos:Number;
		private var _ratio:Number = 0;
		private var maskHeight:Number = 0;
		private var skin:ABScrollbarSkin;

		
		public function VScrollbar (skin:ABScrollbarSkin, scrollObject:DisplayObject, maskHeight:Number, snapHeight:Number=1) 
		{
			
			this.snapHeight = snapHeight;
			this.scrollObject = scrollObject;
			this.maskHeight = maskHeight;
			
			initPos = scrollObject.y;
			initSkin(skin);
			
			addEventListener(Event.ADDED_TO_STAGE, initStage);
			addEventListener(Event.REMOVED_FROM_STAGE,dispose);
			
			super(); 
		}
	
	
		public function updateDisplay ():void {
			if(totalSnap>showPerpage) {
				visible =true;
				scrollObject.addEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
			} else {
				visible =false;
				scrollObject.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
			}
		}
		
		public override function set height (h:Number):void {
			var btnHeight:Number = 0;
			if(skin.upBtn) btnHeight += skin.upBtn.height;
			if(skin.downBtn) btnHeight += skin.downBtn.height;
			skin.bar.height = h-btnHeight;
			positionSkin();
		}
		
		private function initStage (e:Event):void {
			updateDisplay();
			addEventListener(Event.ENTER_FRAME, update);
			update();
		}
		protected function positionSkin ():void {
			if(skin.upBtn) skin.upBtn.y = 0;
			skin.bar.y = (skin.upBtn) ? skin.upBtn.y+skin.upBtn.height : 0;
			if(skin.drag)  skin.drag.y = top;
			if(skin.downBtn) skin.downBtn.y = bottom;
		}
		
		private function initSkin (skin:ABScrollbarSkin):void {
			this.skin = skin;
			
			addChild(skin.bar);
			if(skin.upBtn) addChild(skin.upBtn);
			if(skin.drag) addChild(skin.drag);
			if(skin.downBtn) addChild(skin.downBtn);
			positionSkin ();
			
			if(skin.bar) skin.bar.addEventListener(MouseEvent.MOUSE_DOWN, clickBarHandler);
			if(skin.drag) skin.drag.addEventListener(MouseEvent.MOUSE_DOWN, dragBarHandler);
			if(skin.upBtn) skin.upBtn.addEventListener(MouseEvent.CLICK, prevHandler);
			if(skin.downBtn) skin.downBtn.addEventListener(MouseEvent.CLICK, nextHandler);
			
		}
		

		public function get ratio ():Number {			return _ratio;}
		public function set ratio (r:Number):void {		_ratio = Math.min(1,Math.max(0,r));}
		
		private function update (e:Event=null):void {
			var pos:Number = top+(ratio*(skin.bar.height-dragHeight));
			if(skin.drag) skin.drag.y += (pos-skin.drag.y) *0.3;
			if(scrollObject) {
				var oPos:Number = initPos-(Math.round(ratio*(totalSnap-showPerpage))*snapHeight);
				scrollObject.y += (oPos-scrollObject.y) *0.3;
			}
		}
		
		private function updateBySnap (s:Number):void {
			var t:Number = Math.ceil(totalSnap/showPerpage);
			ratio = (s/t);
		}

		
		private function nextHandler (e:MouseEvent=null):void {
			var t:Number = 4*(1/(totalSnap-showPerpage));
			ratio += t;
		}
		private function prevHandler (e:MouseEvent=null):void {	
			var t:Number = 4*(1/(totalSnap-showPerpage));
			ratio -= t;
		}
		private function mouseWheelHandler (e:MouseEvent):void {
			ratio-=e.delta*0.03;
			e.stopPropagation();
		}
		private function clickBarHandler (e:MouseEvent=null):void {
			ratio = (mouseY-top)/skin.bar.height;
		}
		private function dragBarHandler (e:MouseEvent=null):void {
			stage.addEventListener(MouseEvent.MOUSE_UP, stopDragHandler);
			stage.addEventListener(MouseEvent.MOUSE_MOVE, moveHandler);
		}
		private function moveHandler (e:MouseEvent=null):void {
			var ty:Number = Math.min(bottom,Math.max(top, mouseY))-top;
			ratio = ty/skin.bar.height;
		}
		
		private function stopDragHandler (e:MouseEvent=null):void {
			stage.removeEventListener(MouseEvent.MOUSE_UP, stopDragHandler);
			stage.removeEventListener(MouseEvent.MOUSE_MOVE, moveHandler);
		}
		private function dispose (e:Event=null):void {
			removeEventListener(Event.ENTER_FRAME, update);
			scrollObject.removeEventListener(MouseEvent.MOUSE_WHEEL, mouseWheelHandler);
			stopDragHandler();
		}
		
		private function get top ():Number {			return skin.bar.y;}
		private function get bottom ():Number {			return skin.bar.height+skin.bar.y;}
		private function get totalSnap ():uint {		return Math.ceil(scrollObject.height/snapHeight);}
		private function get showPerpage ():uint {		return Math.floor(maskHeight/snapHeight);}
		private function get dragHeight ():Number {		return (skin.drag) ? skin.drag.height : 0;}
		
	}
}